#include <assert.h>
#include <stdio.h>
#include "reactor.h"
#include "event_demultiplexer.h"
#include "util.h"
#define INITSIZE 100

namespace reactor
{
    class ReactorImplementation
        {
    public:

        ReactorImplementation();

        ~ReactorImplementation();

		int RegisterHandler(EventHandlerPtr handler, event_t evt);

		int RemoveHandler(EventHandlerPtr handler);

        void HandleEvents();

		void ReleaseHandlers();

        int RegisterTimerTask(heap_timer* timerevent);
    private:

        EventDemultiplexer *                m_demultiplexer;
		std::map<handle_t, std::shared_ptr<EventHandler>>  m_handlers;
        time_heap* m_eventtimer;
    };

    ///////////////////////////////////////////////////////////////////////////////

    Reactor::Reactor()
    {
        m_reactor_impl = new ReactorImplementation();
    }

    Reactor::~Reactor()
    {
        delete m_reactor_impl;
    }

	int Reactor::RegisterHandler(EventHandlerPtr handler, event_t evt)
    {						
		//printf("Register Handler event fd =  %d  evt = %d\n", handler->GetHandle(), evt);
        return m_reactor_impl->RegisterHandler(handler, evt);
    }

	int Reactor::RemoveHandler(EventHandlerPtr handler)
    {
        return m_reactor_impl->RemoveHandler(handler);
    }

	void Reactor::ReleaseHandlers()
	{
		m_reactor_impl->ReleaseHandlers();
	}
    void Reactor::HandleEvents()
    {
        m_reactor_impl->HandleEvents();
    }

    int Reactor::RegisterTimerTask(heap_timer* timerevent)
    {
        return m_reactor_impl->RegisterTimerTask(timerevent);
    }

    ///////////////////////////////////////////////////////////////////////////////

    ReactorImplementation::ReactorImplementation()
    {
        m_demultiplexer = new EpollDemultiplexer();
        m_eventtimer = new time_heap(INITSIZE);
    }

    ReactorImplementation::~ReactorImplementation()
    {
        delete m_demultiplexer;
    }

	int ReactorImplementation::RegisterHandler(EventHandlerPtr handler, event_t evt)
    {
        handle_t handle = handler->GetHandle();		
		std::map<handle_t, EventHandlerPtr>::iterator it = m_handlers.find(handle);
        if (it == m_handlers.end())
        {
            m_handlers[handle] = handler;
        }
        return m_demultiplexer->RequestEvent(handle, evt);
    }

	int ReactorImplementation::RemoveHandler(EventHandlerPtr handler)
    {		
        handle_t handle = handler->GetHandle();		
        m_handlers.erase(handle);
        return m_demultiplexer->UnrequestEvent(handle);
    }

	void ReactorImplementation::ReleaseHandlers()
	{		
		std::map<handle_t, EventHandlerPtr>::iterator iter;
		do 
		{
			iter = m_handlers.begin();
			if (iter != m_handlers.end())
				iter->second->HandleClose();
			else
				break;
		} while (true);
	}

    //parm timeout is useless.
    void ReactorImplementation::HandleEvents()
    {
        unsigned int timeout = 0;
        if (m_eventtimer->top() == NULL)
        {
            timeout = 0;
        }
        else
        {
			int64_t tick = util::timeMicro();
			timeout = ((m_eventtimer->top())->expire - tick)/1000;
        }
        m_demultiplexer->WaitEvents(&m_handlers, timeout, m_eventtimer);
    }

    int ReactorImplementation::RegisterTimerTask(heap_timer* timerevent)
    {
        if (timerevent == NULL)
            return -1;
        m_eventtimer->add_timer(timerevent);
        return 0;
    }

} // namespace reactor

